package com.unitedvision.persistence.domain;

import java.time.Month;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import com.unitedvision.core.domain.Payer;
import com.unitedvision.core.domain.Payment;
import com.unitedvision.core.exception.WrongFormatException;

@Entity
@Table (name = "payment")
public class PaymentEntity {
	private int id;
	private CompanyCustomerEntity companyCustomer;
	private OperatorEntity operator;
	private Date paymentDate;
	private long cost;
	private PeriodeValue periode;
	
	public PaymentEntity() {
		super();
	}

	public PaymentEntity(Payer payer, OperatorEntity operatorEntity, PeriodeValue periodeValue, Date paymentDate, long cost) {
		super();
		this.companyCustomer = (CompanyCustomerEntity)payer.getPayableCustomer();
		this.operator = operatorEntity;
		this.periode = periodeValue;
		this.paymentDate = paymentDate;
		this.cost = cost;
	}

	public PaymentEntity(Payment payment) throws WrongFormatException {
		super();
		this.companyCustomer = CompanyCustomerEntity.create(payment.getCompanyCustomer());
		this.operator = OperatorEntity.create(payment.getOperator());
		this.periode = PeriodeValue.create(payment.getPeriode());
		this.paymentDate = payment.getPaymentDate();
		this.cost = payment.getCost();
	}

	@Id
	@GeneratedValue
	@Column (name = "id")
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	@ManyToOne (fetch = FetchType.EAGER)
	@JoinColumn (name = "company_customer_id", referencedColumnName = "id")
	public CompanyCustomerEntity getCompanyCustomer() {
		return companyCustomer;
	}

	public void setCompanyCustomer(CompanyCustomerEntity companyCustomerEntity) {
		this.companyCustomer = companyCustomerEntity;
	}

	@ManyToOne (fetch = FetchType.EAGER)
	@JoinColumn (name = "operator_id", referencedColumnName = "id")
	public OperatorEntity getOperator() {
		return operator;
	}

	public void setOperator(OperatorEntity operatorEntity) {
		this.operator = operatorEntity;
	}

	@Embedded
	public PeriodeValue getPeriode() {
		return periode;
	}

	public void setPeriode(PeriodeValue periodeValue) {
		this.periode = periodeValue;
	}

	@Temporal (TemporalType.DATE)
	@Column (name = "payment_date")
	public Date getPaymentDate() {
		return paymentDate;
	}

	public void setPaymentDate(Date paymentDate) {
		this.paymentDate = paymentDate;
	}

	@Column (name = "cost")
	public long getCost() {
		return cost;
	}

	public void setCost(long cost) {
		this.cost = cost;
	}

	@Transient
	public CompanyEntity getCompany() {
		if (operator != null)
			return operator.getCompany();
		return null;
	}

	@Transient
	public int getYear() {
		if (periode == null)
			return 0;
		return periode.getYear();
	}
	
	public void setYear(int year) {
		if (periode == null)
			periode = new PeriodeValue();
		periode.setYear(year);
	}
	
	@Transient
	public Month getMonth() {
		if (periode == null)
			return Month.JANUARY;
		return periode.getMonth();
	}
	
	public void setMonth(Month month) {
		if (periode == null)
			periode = new PeriodeValue();
		periode.setMonth(month);
	}

	public Payment toPayment() {
		return new Payment(id, companyCustomer.toCompanyCustomer(), operator.toOperator(), periode.toPeriode(), paymentDate, cost);
	}
	
	public static PaymentEntity create(Payer payer, OperatorEntity operatorEntity, PeriodeValue periodeValue, Date paymentDate, long cost) {
		return new PaymentEntity(payer, operatorEntity, periodeValue, paymentDate, cost);
	}
	
	public static PaymentEntity create(Payment payment) throws WrongFormatException {
		return new PaymentEntity(payment);
	}

	@Override
	public String toString() {
		return "PaymentEntity [id=" + id + ", companyCustomer="
				+ companyCustomer + ", operator=" + operator + ", paymentDate="
				+ paymentDate + ", cost=" + cost + ", periode=" + periode + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((companyCustomer == null) ? 0 : companyCustomer.hashCode());
		result = prime * result + (int) (cost ^ (cost >>> 32));
		result = prime * result + id;
		result = prime * result
				+ ((operator == null) ? 0 : operator.hashCode());
		result = prime * result
				+ ((paymentDate == null) ? 0 : paymentDate.hashCode());
		result = prime * result + ((periode == null) ? 0 : periode.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		PaymentEntity other = (PaymentEntity) obj;
		if (companyCustomer == null) {
			if (other.companyCustomer != null)
				return false;
		} else if (!companyCustomer.equals(other.companyCustomer))
			return false;
		if (cost != other.cost)
			return false;
		if (id != other.id)
			return false;
		if (operator == null) {
			if (other.operator != null)
				return false;
		} else if (!operator.equals(other.operator))
			return false;
		if (paymentDate == null) {
			if (other.paymentDate != null)
				return false;
		} else if (!paymentDate.equals(other.paymentDate))
			return false;
		if (periode == null) {
			if (other.periode != null)
				return false;
		} else if (!periode.equals(other.periode))
			return false;
		return true;
	}
}
